home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / examples / demo / demosrc / d_flyby.pro < prev    next >
Text File  |  1997-07-08  |  21KB  |  659 lines

  1. ;$Id: d_flyby.pro,v 1.29 1997/04/17 18:35:42 tremblay Exp $
  2. ;
  3. ;  Copyright (c) 1997, Research Systems, Inc. All rights reserved.
  4. ;       Unauthorized reproduction prohibited.
  5. ;
  6. ;+
  7. ;  FILE:
  8. ;       d_flyby.pro
  9. ;
  10. ;  CALLING SEQUENCE: d_flyby
  11. ;
  12. ;  PURPOSE:
  13. ;       Shows the texture mapping and a flyby animation.
  14. ;
  15. ;  MAJOR TOPICS: Visualization
  16. ;
  17. ;  CATEGORY:
  18. ;       IDL 5.0
  19. ;
  20. ;  INTERNAL FUNCTIONS and PROCEDURES:
  21. ;       pro StopAndReset       -  Stop the ride sequence and reset
  22. ;       pro d_flyby_Event      -  Event handler
  23. ;       pro d_flyby_Cleanup    -  Cleanup
  24. ;       pro d_flyby            -  Main procedure
  25. ;
  26. ;  EXTERNAL FUNCTIONS, PROCEDURES, and FILES:
  27. ;       pro trackball__define   -  Create the trackball object
  28. ;       pro gettips           -  Read the tip file
  29. ;       pro widtips           -  Create the tip widgets
  30. ;       pro sizetips          -  Size the tip widgets
  31. ;       flyby.txt
  32. ;       flyby.tip
  33. ;       leadvil.sav
  34. ;       elev_t.dat
  35. ;
  36. ;  REFERENCE: IDL Reference Guide, IDL User's Guide
  37. ;
  38. ;  NAMED STRUCTURES:
  39. ;       none.
  40. ;
  41. ;  COMMON BLOCS:
  42. ;       none.
  43. ;
  44. ;  MODIFICATION HISTORY:
  45. ;       1/97,   DAT   - Written.
  46. ;-
  47. ;----------------------------------------------------------------------------
  48. ;
  49. ;  Purpose:  Stop the flyby sequence and reset the surface
  50. ;            to its initial  state (Position and orientation).
  51. ;
  52. pro StopAndReset, $
  53.     sEvent       ; IN: event sturcture
  54.  
  55.     WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  56.  
  57.     sState.oSurfaceModel->SetProperty, $
  58.         TRANSFORM=sState.initTranslationTM
  59.     sState.oSurfaceRotationModel->SetProperty, $
  60.         TRANSFORM=sState.initRotationTM
  61.     sState.oWindow->Draw, sState.oView
  62.  
  63.     sState.stopFlag = 0
  64.  
  65.     WIDGET_CONTROL, sState.wRideButton, SENSITIVE=1
  66.     WIDGET_CONTROL, sState.wFileButton, SENSITIVE=1
  67.     WIDGET_CONTROL, sState.wHelpButton, SENSITIVE=1
  68.     WIDGET_CONTROL, sState.wFrameSpeedSlider, SENSITIVE=1
  69.     WIDGET_CONTROL, sState.wResetButton, SENSITIVE=0
  70.     WIDGET_CONTROL, sEvent.top, /CLEAR_EVENTS
  71.  
  72.     WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  73. end
  74.  
  75. ;----------------------------------------------------------------------------
  76. ;
  77. ;  Purpose:  Event handler.
  78. ;
  79. pro d_flyby_event, $
  80.     sEvent
  81.  
  82.     if (TAG_NAMES(sEvent, /STRUCTURE_NAME) EQ  $
  83.         'WIDGET_KILL_REQUEST') then begin
  84.         WIDGET_CONTROL, sEvent.top, /DESTROY
  85.         RETURN
  86.     endif
  87.  
  88.     WIDGET_CONTROL, sEvent.id, GET_UVALUE= uvalue
  89.  
  90.     case uvalue of
  91.  
  92.         'RESET' : begin
  93.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  94.  
  95.             ;  Setting the stopFlag to 1 will stop the for loops
  96.             ;  in 'RIDE' section below.
  97.             ;
  98.             sState.stopFlag = 1
  99.  
  100.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  101.         end
  102.          
  103.             
  104.         ;  Start the animation.
  105.         ;
  106.         'RIDE' : begin
  107.  
  108.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  109.             sState.stopFlag = 0
  110.             stopFlag = 0
  111.  
  112.             WIDGET_CONTROL, sState.wRideButton, SENSITIVE=0
  113.             WIDGET_CONTROL, sState.wHelpButton, SENSITIVE=0
  114.             WIDGET_CONTROL, sState.wFrameSpeedSlider, SENSITIVE=0
  115.             WIDGET_CONTROL, sState.wResetButton, SENSITIVE=1
  116.  
  117.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  118.  
  119.             for i = 1, 11 do begin
  120.  
  121.                 WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  122.  
  123.                 sState.oSurfaceModel->Translate,0.035, 0.0, 0.13 
  124.                 sState.oSurfaceRotationModel->GetProperty, $
  125.                     TRANSFORM = tm
  126.                 sState.oSurfaceRotationModel->Rotate, $
  127.                     [tm[0,0], tm[0,1], tm[0,2]], -3.5 
  128.                 sState.oWindow->Draw, sState.oView
  129.                 wait, sState.timeDelay
  130.  
  131.                 WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  132.  
  133.                 ;  Catch the quit ofr close event from the close box.
  134.                 ;
  135.                 result = WIDGET_EVENT(sEvent.top, /NOWAIT, BAD_ID=badID)
  136.  
  137.                 ;  This event is created by the close box.
  138.                 ;  The top level base is destroyed. Upon RETURN,
  139.                 ;  the code goes to the cleanup procedure directly.
  140.                 ;
  141.                 if(badID NE 0) then begin
  142.                      RETURN
  143.                 endif
  144.  
  145.                 ;  The stopFlag is set to 1 only by pushing the
  146.                 ;  'Stop and Reset' button. That is event is
  147.                 ;  processed after the draw command in the for loops
  148.                 ;  below. 
  149.                 ;
  150.                 WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  151.                 stopFlag = sState.stopFlag
  152.                 WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  153.                 if (stopFlag EQ 1) then begin
  154.                     StopAndReset, sEvent
  155.                     RETURN
  156.                 endif
  157.  
  158.             endfor
  159.  
  160.             for i = 1, 6 do begin
  161.                 WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  162.                 sState.oSurfaceModel->Translate, -0.012, 0.0, 0.12 
  163.                 sState.oWindow->Draw, sState.oView
  164.                 wait, sState.timeDelay
  165.                 WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  166.  
  167.                 ;  Catch the quit ofr close event from the close box.
  168.                 ;
  169.                 result = WIDGET_EVENT(sEvent.top, /NOWAIT, BAD_ID=badID)
  170.  
  171.                 ;  This event is created by the close box.
  172.                 ;
  173.                 if(badID NE 0) then begin
  174.                      RETURN
  175.                 endif
  176.  
  177.                 ;  The stopFlag is set to 1 only by pushing the
  178.                 ;  'Stop and Reset' button. That is event is
  179.                 ;  processed after the draw command in the for loops
  180.                 ;  below. 
  181.                 ;
  182.                 WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  183.                 stopFlag = sState.stopFlag
  184.                 WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  185.                 if (stopFlag EQ 1) then begin
  186.                     StopAndReset, sEvent
  187.                     RETURN
  188.                 endif
  189.  
  190.             endfor
  191.  
  192.             for i = 1, 8 do begin
  193.                 WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  194.                 sState.oSurfaceRotationModel->GetProperty, $
  195.                     TRANSFORM = tm
  196.                 sState.oSurfaceRotationModel->Rotate, $
  197.                     [tm[2,0], tm[2,1], tm[2,2]], 15 
  198.                 sState.oWindow->Draw, sState.oView
  199.                 wait, sState.timeDelay
  200.                 WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  201.  
  202.                 ;  Catch the quit ofr close event from the close box.
  203.                 ;
  204.                 result = WIDGET_EVENT(sEvent.top, /NOWAIT, BAD_ID=badID)
  205.  
  206.                 ;  This event is created by the close box.
  207.                 ;
  208.                 if(badID NE 0) then begin
  209.                      RETURN
  210.                 endif
  211.  
  212.                 ;  The stopFlag is set to 1 only by pushing the
  213.                 ;  'Stop and Reset' button. That is event is
  214.                 ;  processed after the draw command in the for loops
  215.                 ;  below. 
  216.                 ;
  217.                 WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  218.                 stopFlag = sState.stopFlag
  219.                 WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  220.                 if (stopFlag EQ 1) then begin
  221.                     StopAndReset, sEvent
  222.                     RETURN
  223.                 endif
  224.  
  225.             endfor
  226.  
  227.             for i = 1, 5 do begin
  228.                 WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  229.                 sState.oSurfaceModel->translate, 0.0, -0.035, 0.09
  230.                 sState.oWindow->Draw, sState.oView
  231.                 wait, sState.timeDelay
  232.                 WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  233.  
  234.                 ;  Catch the quit ofr close event from the close box.
  235.                 ;
  236.                 result = WIDGET_EVENT(sEvent.top, /NOWAIT, BAD_ID=badID)
  237.  
  238.                 ;  This event is created by the close box.
  239.                 ;
  240.                 if(badID NE 0) then begin
  241.                      RETURN
  242.                 endif
  243.  
  244.                 ;  The stopFlag is set to 1 only by pushing the
  245.                 ;  'Stop and Reset' button. That is event is
  246.                 ;  processed after the draw command in the for loops
  247.                 ;  below. 
  248.                 ;
  249.                 WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  250.                 stopFlag = sState.stopFlag
  251.                 WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  252.                 if (stopFlag EQ 1) then begin
  253.                     StopAndReset, sEvent
  254.                     RETURN
  255.                 endif
  256.  
  257.             endfor
  258.  
  259.             ;  Reset the view to initial transformation.
  260.             ;
  261.             StopAndReset, sEvent
  262.  
  263.         end     ;  of RIDE
  264.  
  265.         ;  Set the time delay between each redraw. This time is added to
  266.         ;  to the drawing time.
  267.         ;
  268.         'SPEED': begin
  269.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  270.  
  271.             ;  Get the slider value.
  272.             ;
  273.             WIDGET_CONTROL, sState.wFrameSpeedSlider, GET_VALUE=sValue
  274.  
  275.             ;  The slider value range is from 0 to 10. Make
  276.             ;  the maximum delay to be 1.0 seconds.
  277.             ;
  278.             sState.timeDelay = 1.0 - (FLOAT(sValue)/ 10.0)
  279.  
  280.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  281.  
  282.         end     ;  of SPEED
  283.  
  284.         ;  Handle the event generated within the drawing area
  285.         ;
  286.         'DRAW': begin
  287.  
  288.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  289.  
  290.             ;  Expose.
  291.             ;
  292.             if (sEvent.type eq 4) then begin
  293.                 sState.oWindow->Draw, sState.oView
  294.                 WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  295.                 RETURN
  296.             endif
  297.  
  298.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  299.  
  300.         end   ;   of DRAW
  301.  
  302.         'QUIT' : BEGIN
  303.             WIDGET_CONTROL, sEvent.top, /DESTROY
  304.         end   ; of QUIT
  305.  
  306.         'ABOUT' : BEGIN
  307.  
  308.             ;  Verify that there is only one instance of Xregistered
  309.             ;
  310.             if (Xregistered('XDisplayFile') NE 0) then RETURN
  311.                 XDisplayFile, filepath("flyby.txt", $
  312.                     SUBDIR=['examples','demo','demotext']), $
  313.                 DONE_BUTTON='Done', $
  314.                 TITLE="Texture", $
  315.                 GROUP=sEvent.top, WIDTH=55, HEIGHT=14
  316.         end   ; of ABOUT
  317.  
  318.     endcase
  319.  
  320. end
  321.  
  322. ;-----------------------------------------------------------------
  323. ;
  324. ;    PURPOSE : cleanup procedure. restore colortable, destroy objects.
  325. ;
  326. pro d_flyby_Cleanup, wTopBase
  327.  
  328.     WIDGET_CONTROL, wTopBase, GET_UVALUE=sState, /NO_COPY
  329.  
  330.     ;  Destroy the top objects.
  331.     ;
  332.     OBJ_DESTROY, sState.oView
  333.     OBJ_DESTROY, sState.oImage
  334.     OBJ_DESTROY, sState.oText
  335.     OBJ_DESTROY, sState.oFont
  336.  
  337.     ;  Restore the color table.
  338.     ;
  339.     TVLCT, sState.colorTable
  340.  
  341.     if WIDGET_INFO(sState.groupBase, /VALID_ID) then $
  342.         WIDGET_CONTROL, sState.groupBase, /MAP
  343.  
  344. end   ;  of d_flyby_Cleanup
  345.  
  346. ;-----------------------------------------------------------------
  347. ;
  348. ;    PURPOSE : show the texture mapping capability
  349. ;
  350. PRO d_flyby, $
  351.     TEXCOORDS = texcoords, $   ; IN: (opt) texture coordinates
  352.     GROUP=group, $             ; IN: (opt) group identifier
  353.     APPTLB = appTLB            ; OUT: (opt) TLB of this application
  354.  
  355.     ; Check the validity of the group identifier.
  356.     ;
  357.     ngroup = N_ELEMENTS(group)
  358.     if (ngroup NE 0) then begin
  359.         check = WIDGET_INFO(group, /VALID_ID)
  360.         if (check NE 1) then begin
  361.             print,'Error, the group identifier is not valid'
  362.             print, 'Return to the main application'
  363.             RETURN
  364.         endif
  365.         groupBase = group
  366.     endif else groupBase = 0L
  367.  
  368.     ;  Get the screen size.
  369.     ;
  370.     Device, GET_SCREEN_SIZE = screenSize
  371.  
  372.     ;  Set up dimensions of the drawing (viewing) area.
  373.     ;
  374.     xdim = screenSize[0]*0.6
  375.     ydim = xdim*0.8
  376.  
  377.     ;  Get the current color vectors to restore 
  378.     ;  when this application is exited.
  379.     ;
  380.     TVLCT, savedR, savedG, savedB, /GET
  381.  
  382.     ;  Build color table from color vectors
  383.     ;
  384.     colorTable = [[savedR],[savedG],[savedB]]
  385.  
  386.     ;  Get the tips.
  387.     ;
  388.     sText = getTips(filepath('flyby.tip', $
  389.         SUBDIR=['examples','demo', 'demotext']))
  390.  
  391.     ;  Create widgets.
  392.     ;
  393.     if (N_ELEMENTS(group) EQ 0) then begin
  394.         wTopBase = WIDGET_BASE(/COLUMN, $
  395.             TITLE="Flyby", $
  396.             XPAD=0, YPAD=0, $
  397.             /TLB_KILL_REQUEST_EVENTS, $
  398.             TLB_FRAME_ATTR=1, MBAR=barBase)
  399.     endif else begin
  400.         wTopBase = WIDGET_BASE(/COLUMN, $
  401.             TITLE="Flyby", $
  402.             XPAD=0, YPAD=0, $
  403.             /TLB_KILL_REQUEST_EVENTS, $
  404.             GROUP_LEADER=group, $
  405.             TLB_FRAME_ATTR=1, MBAR=barBase)
  406.     endelse
  407.  
  408.         ;  Create the menu bar. It contains the file/quit,
  409.         ;  edit/ shade-style, help/about.
  410.         ;
  411.         wFileButton = WIDGET_BUTTON(barBase, VALUE='File', /MENU)
  412.  
  413.             wQuitButton = WIDGET_BUTTON(wFileButton, $
  414.                 VALUE='Quit', UVALUE='QUIT')
  415.  
  416.          ;  Create the menu bar item help that contains the about button
  417.          ;
  418.          wHelpButton = WIDGET_BUTTON(barBase, VALUE='About', /HELP, /MENU)
  419.  
  420.              wAboutButton = WIDGET_BUTTON(wHelpButton, $
  421.                  VALUE='About Flyby', UVALUE='ABOUT')
  422.  
  423.          ;  Create a sub base of the top base (wTopBase)
  424.          ;
  425.          subBase = WIDGET_BASE(wTopBase, COLUMN=2)
  426.  
  427.              ;  Create the left Base that contains the functionality buttons
  428.              ;  Notably the object list and the option list
  429.              ;
  430.              wLeftbase = WIDGET_BASE(subBase, /ALIGN_CENTER, /COLUMN)
  431.  
  432.                  wRideBase = WIDGET_BASE(wLeftBase, YPAD=15, /COLUMN)
  433.  
  434.                      wRideBaseLabel = WIDGET_LABEL(wRideBase, $
  435.                          VALUE = "Helicopter Ride")
  436.  
  437.                      wRideButton = WIDGET_BUTTON(wRideBase, $
  438.                          VALUE='Ride', UVALUE='RIDE')
  439.  
  440.                  wSliderBase = WIDGET_BASE(wLeftBase, $
  441.                     /COLUMN,/ALIGN_CENTER)
  442.  
  443.                     wAnimationLbl = WIDGET_LABEL(wSliderBase, $
  444.                         VALUE='Animation Speed', $
  445.                         /ALIGN_CENTER)
  446.  
  447.                     wfasttLbl = WIDGET_LABEL(wSliderBase, VALUE='Fast', $
  448.                         /ALIGN_CENTER)
  449.  
  450.                     wFrameSpeedSlider = WIDGET_SLIDER(wSliderBase,$
  451.                         /ALIGN_CENTER, $
  452.                         /DRAG, VALUE = 10, UVALUE='SPEED', $
  453.                         MAXIMUM = 10, MINIMUM = 0,/VERTICAL, /SUPPRESS_VALUE)
  454.  
  455.                     wSlowLbl = WIDGET_LABEL(wSliderBase, VALUE='Slow', $
  456.                           /ALIGN_CENTER)
  457.  
  458.                  wResetBase = WIDGET_BASE(wLeftBase, $
  459.                     /COLUMN)
  460.  
  461.                      wResetButton = WIDGET_BUTTON(wResetBase, $
  462.                          VALUE='Stop and Reset', UVALUE='RESET')
  463.  
  464.              ;  Create the right Base that has the drawing area
  465.              ;
  466.              wRightBase = WIDGET_BASE(subBase, /COLUMN)
  467.  
  468.                  ;  Draw area.
  469.                  ;
  470.                  wDraw = WIDGET_DRAW(wRightBase, $
  471.                      GRAPHICS_LEVEL=2, $
  472.                      XSIZE=xdim, YSIZE=ydim, /BUTTON_EVENTS, $
  473.                      UVALUE='DRAW', $
  474.                      RETAIN=0, /EXPOSE_EVENT)
  475.  
  476.         ;  Create tips texts.
  477.         ;
  478.         wStatusBase = WIDGET_BASE(wTopBase, MAP=0, /ROW)
  479.  
  480.             nWidgets = 2
  481.             wText = LONARR(nWidgets)
  482.             widTips, wStatusBase, sText.text, XSIZE=36, $
  483.                 YSIZE=3, NWIDGETS=nWidgets, wText
  484.  
  485.     ;  Realize the base widget. 
  486.     ;
  487.     WIDGET_CONTROL, wTopBase, /REALIZE
  488.  
  489.     ;  Returns the top level base in the appTLB keyword
  490.     ;
  491.     appTLB = wTopBase
  492.  
  493.     ;  Size the tips widgets.
  494.     ;
  495.     sizeTips, wTopBase, wText, wStatusBase
  496.  
  497.     WIDGET_CONTROL, wTopBase, SENSITIVE=0
  498.  
  499.     ;  Grab the window id of the drawable.
  500.     ;
  501.     WIDGET_CONTROL, wDraw, GET_VALUE=oWindow
  502.  
  503.     ;  Put centerize the surface.
  504.     ;
  505.     bias = -0.5
  506.  
  507.     myview = [0+bias, 0+bias, 1, 1]
  508.  
  509.     ;  Create view.  
  510.     ;
  511.     oView = OBJ_NEW('idlgrview', $
  512.         PROJECTION=2, EYE=3, ZCLIP=[2.9,-10.0], $
  513.         VIEWPLANE_RECT=myview, COLOR=[0, 0, 0])
  514.  
  515.     ;  Make the starting up text location centered.
  516.     ;
  517.     textLocation = [myview[0]+0.5*myview[2], myview[1]+0.5*myview[3]]
  518.  
  519.     ;  Create and display the PLEASE WAIT text.
  520.     ;
  521.     oFont = OBJ_NEW('IDLgrFont', 'Helvetica', SIZE=10)
  522.     oText = OBJ_NEW('IDLgrText', $
  523.         'Starting up  Please wait...', $
  524.         ALIGN=0.5, $
  525.         LOCATION=textLocation, $
  526.         COLOR=[255,255,0], FONT=oFont)
  527.  
  528.  
  529.     ;  Create model.
  530.     ;
  531.     oTopModel = OBJ_NEW('idlgrmodel')
  532.     oSurfaceModel = OBJ_NEW('idlgrmodel')
  533.     oSurfaceRotationModel = OBJ_NEW('idlgrmodel')
  534.     oSurfaceScalingModel = OBJ_NEW('idlgrmodel')
  535.     oTopModel->Add, oSurfaceModel
  536.     oSurfaceModel->Add, oSurfaceRotationModel
  537.     oSurfaceRotationModel->Add, oSurfaceScalingModel
  538.  
  539.     ;  Place the model in the view.
  540.     ;
  541.     oView->Add, oTopModel
  542.  
  543.     ;  Add the text.
  544.     ;
  545.     oTopModel->Add, oText
  546.  
  547.     ;  Draw the starting up screen.
  548.     ;
  549.     oWindow->Draw, oView
  550.  
  551.     RESTORE, filepath('lvdem.sav', SUBDIR=['examples','demo','demodata'])
  552.     z = lvdemdata
  553.  
  554.     sz = SIZE(z)
  555.     maxx = sz[1] - 1
  556.     maxy = sz[2] - 1
  557.     maxz = MAX(z, MIN=minz)
  558.  
  559.     ;  Compute coordinate conversion to normalize.
  560.     ;
  561.     xs = [0+bias, 1.0/maxx]
  562.     ys = [0+bias, 1.0/maxy]
  563.  
  564.     minz2 = minz - 1000.0
  565.     maxz2 = maxz + 1000.0
  566.     zs = [-minz2/(maxz2-minz2)+bias, 1.0/(maxz2-minz2)]
  567.  
  568.     ;  Create texture map. Read the image first.
  569.     ;
  570.     READ_JPEG, filepath('lvimage.jpg', $
  571.       SUBDIR=['examples','demo','demodata']), lvimage, TRUE=3
  572.     
  573.     oImage = OBJ_NEW('IDLgrImage', lvimage, INTERLEAVE=2)
  574.  
  575.     ;  Create the surface object.
  576.     ;
  577.     oSurface = OBJ_NEW('IDLgrSurface', z, STYLE=2, SHADING=1, $
  578.     COLOR=[255,255,255], $
  579.         TEXTURE_MAP=oImage, $
  580.     XCOORD_CONV=xs, YCOORD_CONV=ys, ZCOORD_CONV=zs)
  581.  
  582.     oSurfaceScalingModel->Add, oSurface
  583.  
  584.     z1 = z
  585.     oSurface->SetProperty, DATAZ=z1
  586.  
  587.     ;  Create a light.
  588.     ;
  589.     oLight1 = OBJ_NEW('IDLgrLight', TYPE=0, INTENSITY=1., COLOR=[255,255,255])
  590.     oTopModel->Add, oLight1
  591.     oLight2 = OBJ_NEW('IDLgrLight', LOCATION=[-2,2,-2], TYPE=1)
  592.     oTopModel->Add, oLight2
  593.  
  594.     ;  Set the initial view.
  595.     ;
  596.     sc = 3.0
  597.     oSurfaceScalingModel->Scale, 1.0, 1.0, sc
  598.     oSurfaceRotationModel->Rotate, [1,0,0],-35
  599.  
  600.     ;  Get the initial transformation.
  601.     ;
  602.     oSurfaceModel->GetProperty, TRANSFORM = initTranslationTM
  603.     oSurfaceRotationModel->GetProperty, TRANSFORM = initRotationTM
  604.  
  605.     ;  Create the state structure.
  606.     ;
  607.     sState = { $
  608.         btndown: 0b, $                       ; 0 = not pressed, 1= pressed
  609.         wDraw: wDraw, $                      ; Widget draw ID
  610.         timeDelay: 0.0, $                      ; Animation frame delay (sec.)
  611.         OSurfaceModel: oSurfaceModel, $      ; Models
  612.         OSurfaceScalingModel: $
  613.             oSurfaceScalingModel, $
  614.         OSurfaceRotationModel: $
  615.             oSurfaceRotationModel, $
  616.         OSurface: oSurface, $                ; Surface object
  617.         OView: oView, $                      ; View object
  618.         WTopBase : wTopbase, $               ; Top level base
  619.         WFrameSpeedSlider : $
  620.             wFrameSpeedSlider, $             ; Animation speed slider
  621.         WFileButton : wFileButton, $         ; Buttons ID
  622.         WRideButton : wRideButton, $                 
  623.         WResetButton : wResetButton, $                 
  624.         WHelpButton : wHelpButton, $
  625.         WQuitButton : wQuitButton, $
  626.         OImage: oImage, $                    ; Image object
  627.         ColorTable: colorTable, $            ; Color table to restore at exit
  628.         Z1: z1, $                            ; Surface height data
  629.         WText: wText, $                      ; Widget text IDs for tips
  630.         InitTranslationTM: $
  631.             initTranslationTM, $             ; Initial transformation matrix
  632.         InitRotationTM: initRotationTM, $    ; Initial rotation of surface
  633.         OWindow: oWindow, $                  ; Window object
  634.         OText: oText, $                      ; Starting up text object
  635.         OFont: oFont, $                      ; Starting up text font object
  636.         StopFlag: 0, $
  637.         groupBase: groupBase $               ; Base of Group Leader
  638.      }  
  639.  
  640.     WIDGET_CONTROL, wTopBase, SET_UVALUE=sState, /NO_COPY
  641.  
  642.     WIDGET_CONTROL, wTopBase, SENSITIVE=1
  643.     WIDGET_CONTROL, wResetButton, SENSITIVE=0
  644.  
  645.     ;  Remove the starting up text.
  646.     ;
  647.     oTopModel->Remove, oText
  648.  
  649.     ;  Draw the screen.
  650.     ;
  651.     oWindow->Draw, oView
  652.  
  653.     XMANAGER, 'd_flyby', wTopBase, $
  654.         EVENT_HANDLER='d_flyby_event', $
  655.         /NO_BLOCK, $
  656.         CLEANUP='d_flyby_Cleanup'
  657.  
  658. end   ;   of  d_flyby
  659.